home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / src / amiga_minrexx.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  10KB  |  403 lines

  1. /* amiga_minrexx.c -- ARexx interface
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.    If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Originally by Radical Eye Software, modified by me.
  22.  */
  23.  
  24. static char *blurb = "Radical Eye MinRexx 0.4.jsh";
  25.  
  26. #include "jade.h"
  27. #include "jade_protos.h"
  28.  
  29. #include <clib/exec_protos.h>
  30. #ifdef _DCC
  31. # define RexxSysBase_DECLARED
  32. #endif
  33. #include <clib/rexxsyslib_protos.h>
  34. #include <string.h>
  35.  
  36. _PR void rexx_init(void);
  37. _PR void rexx_kill(void);
  38.  
  39. _PR VALUE do_sync_rexx(u_char *, bool);
  40. _PR void disp_rexx_port(void);
  41. static struct RexxMsg *send_rexx_cmd(u_char *, int(*)(), u_char *, u_char *, u_char *, long);
  42. _PR struct RexxMsg *sync_rexx_cmd(u_char *, bool, struct RexxMsg *);
  43. _PR struct RexxMsg *async_rexx_cmd(u_char *);
  44. _PR struct RexxMsg *async_rexx_string(u_char *);
  45. _PR void reply_rexx_cmd(struct RexxMsg *, long, long, u_char *);
  46. static void close_rexx_lib(void);
  47. static bool open_rexx_lib(void);
  48. static void reply_to_it(struct RexxMsg *);
  49.  
  50. _PR u_long rexx_sig;
  51.     u_long rexx_sig;
  52.  
  53. static struct MsgPort *rexx_port;
  54. static bool bringer_down;
  55. static long still_need_replies;
  56. static struct RexxMsg *o_rexx_msg;
  57. static VALUE rexx_name;
  58.  
  59. struct RxsLib *RexxSysBase;
  60.  
  61. #define RX_EXTEN "jade"
  62.  
  63. #define MAXRXOUTSTANDING (300)
  64. #define RXERRORIMGONE (100)
  65. #define RXERRORNOCMD (30)
  66.  
  67. _PR VALUE cmd_rexx_async_macro(VALUE name);
  68. DEFUN("rexx-async-macro", cmd_rexx_async_macro, subr_rexx_async_macro, (VALUE name), V_Subr1, DOC_rexx_async_macro) /*
  69. ::doc:rexx_async_macro::
  70. rexx-async-macro NAME
  71. <AMIGA-ONLY>
  72.  
  73. Asynchronously invokes the ARexx macro called NAME.
  74. ::end:: */
  75. {
  76.     DECLARE1(name, STRINGP);
  77.     if(async_rexx_cmd(VSTR(name)))
  78.     return(sym_t);
  79.     return(sym_nil);
  80. }
  81.  
  82. _PR VALUE cmd_rexx_async_str(VALUE str);
  83. DEFUN("rexx-async-str", cmd_rexx_async_str, subr_rexx_async_str, (VALUE str), V_Subr1, DOC_rexx_async_str) /*
  84. ::doc:rexx_async_str::
  85. rexx-async-str STRING
  86. <AMIGA-ONLY>
  87.  
  88. Gets ARexx to asynchronously interpret the string of REXX code STRING.
  89. ::end:: */
  90. {
  91.     DECLARE1(str, STRINGP);
  92.     if(async_rexx_string(VSTR(str)))
  93.     return(sym_t);
  94.     return(sym_nil);
  95. }
  96.  
  97. _PR VALUE cmd_rexx_sync_macro(VALUE name);
  98. DEFUN("rexx-sync-macro", cmd_rexx_sync_macro, subr_rexx_sync_macro, (VALUE name), V_Subr1, DOC_rexx_sync_macro) /*
  99. ::doc:rexx_sync_macro::
  100. rexx-sync-macro NAME
  101. <AMIGA-ONLY>
  102.  
  103. Invokes the ARexx macro NAME synchronously, returning its value when it
  104. exits (this will either be a number or a string.
  105. ::end:: */
  106. {
  107.     DECLARE1(name, STRINGP);
  108.     return(do_sync_rexx(VSTR(name), TRUE));
  109. }
  110.  
  111. _PR VALUE cmd_rexx_sync_str(VALUE str);
  112. DEFUN("rexx-sync-str", cmd_rexx_sync_str, subr_rexx_sync_str, (VALUE str), V_Subr1, DOC_rexx_sync_str) /*
  113. ::doc:rexx_sync_str::
  114. rexx-sync-str STRING
  115. <AMIGA-ONLY>
  116.  
  117. Synchronously executes the string of ARexx commands STRING, returning their
  118. exit value.
  119. ::end:: */
  120. {
  121.     DECLARE1(str, STRINGP);
  122.     return(do_sync_rexx(VSTR(str), FALSE));
  123. }
  124.  
  125. _PR VALUE var_rexx_port_name(VALUE val);
  126. DEFUN("rexx-port-name", var_rexx_port_name, subr_rexx_port_name, (VALUE val), V_Var, DOC_rexx_port_name) /*
  127. ::doc:rexx_port_name::
  128. Variable holding the name of our ARexx port. (Amiga only).
  129. ::end:: */
  130. {
  131.     if(val)
  132.     return(NULL);
  133.     return(rexx_name ? rexx_name : sym_nil);
  134. }
  135.  
  136. void
  137. rexx_init(void)
  138. {
  139.     int i;
  140.     static UBYTE name[32];
  141.     name[0] = V_StaticString;
  142.     Forbid();
  143.     for(i = 1;; i++)
  144.     {
  145.     sprintf(VSTR(name), "JADE.%d", i);
  146.     if(!FindPort(VSTR(name)))
  147.     {
  148.         rexx_port = CreateMsgPort();
  149.         if(rexx_port)
  150.         {
  151.         rexx_port->mp_Node.ln_Name = VSTR(name);
  152.         rexx_port->mp_Node.ln_Pri = 1;
  153.         AddPort(rexx_port);
  154.         rexx_sig = 1 << rexx_port->mp_SigBit;
  155.         rexx_name = name;
  156.         }
  157.     }
  158.     break;
  159.     }
  160.     Permit();
  161.     ADD_SUBR(subr_rexx_async_macro);
  162.     ADD_SUBR(subr_rexx_async_str);
  163.     ADD_SUBR(subr_rexx_sync_macro);
  164.     ADD_SUBR(subr_rexx_sync_str);
  165.     ADD_SUBR(subr_rexx_port_name);
  166. }
  167.  
  168. void
  169. rexx_kill(void)
  170. {
  171.     if(rexx_port)
  172.     {
  173.     RemPort(rexx_port);
  174.     bringer_down = TRUE;
  175.     if(o_rexx_msg)
  176.     {
  177.         o_rexx_msg->rm_Result1 = RXERRORIMGONE;
  178.         ReplyMsg((struct Message *)o_rexx_msg);
  179.         o_rexx_msg = NULL;
  180.     }
  181.     while(still_need_replies)
  182.     {
  183.         WaitPort(rexx_port);
  184.         disp_rexx_port();
  185.     }
  186.     close_rexx_lib();
  187.     DeleteMsgPort(rexx_port);
  188.     rexx_port = NULL;
  189.     }
  190.     rexx_sig = 0;
  191. }
  192.  
  193. /*
  194.  * This function [hopefully] performs a synchronous REXX call, from
  195.  * which we get the result :)
  196.  */
  197. VALUE
  198. do_sync_rexx(u_char *arg, bool isMac)
  199. {
  200.     VALUE result = sym_nil;
  201.     if(rexx_port && open_rexx_lib())
  202.     {
  203.     struct MsgPort *rp;
  204.     if(rp = CreateMsgPort())
  205.     {
  206.         struct RexxMsg *rm;
  207.         if(rm = CreateRexxMsg(rp, RX_EXTEN, rexx_port->mp_Node.ln_Name))
  208.         {
  209.         rm->rm_Action |= RXFF_RESULT;
  210.         if(send_rexx_cmd(arg, reply_to_it, (char *)rm, NULL, NULL, (isMac ? 0 : RXFF_STRING) | RXFF_RESULT))
  211.         {
  212.             u_long rpsigmask = 1 << rp->mp_SigBit;
  213.             u_long sigs;
  214.  
  215.             do {
  216.             sigs = Wait(rpsigmask | rexx_sig);
  217.             disp_rexx_port();
  218.             } while(!(sigs & rpsigmask));
  219.  
  220.             if(GetMsg(rp))
  221.             {
  222.             if(!rm->rm_Result1 && rm->rm_Result2)
  223.             {
  224.                 result = string_dup((u_char *)rm->rm_Result2);
  225.                 if(open_rexx_lib())
  226.                 DeleteArgstring((u_char *)rm->rm_Result2);
  227.             }
  228.             else
  229.                 result = make_number(rm->rm_Result1);
  230.             }
  231.         }
  232.         if(open_rexx_lib())
  233.             DeleteRexxMsg(rm);
  234.         }
  235.         DeleteMsgPort(rp);
  236.     }
  237.     close_rexx_lib();
  238.     }
  239.     return(result);
  240. }
  241.  
  242. static void
  243. close_rexx_lib(void)
  244. {
  245.     if((!still_need_replies) && RexxSysBase)
  246.     {
  247.     CloseLibrary((struct Library *)RexxSysBase);
  248.     RexxSysBase = NULL;
  249.     }
  250. }
  251.  
  252. void
  253. disp_rexx_port(void)
  254. {
  255.     struct RexxMsg *rexxmsg;
  256.     u_char *cmd;
  257.  
  258.     if(!rexx_port)
  259.     return;
  260.  
  261.     while(rexxmsg = (struct RexxMsg *)GetMsg(rexx_port))
  262.     {
  263.     if(rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  264.     {
  265.         if (rexxmsg->rm_Args[1])
  266.         {
  267.         ((int (*)(struct RexxMsg *))(rexxmsg->rm_Args[1]))(rexxmsg);
  268.         }
  269.         DeleteArgstring(rexxmsg->rm_Args[0]);
  270.         DeleteRexxMsg(rexxmsg);
  271.         still_need_replies--;
  272.         close_rexx_lib();
  273.     }
  274.     else
  275.     {
  276.         cmd = (u_char *)rexxmsg->rm_Args[0];
  277.         while (*cmd > 0 && *cmd <= ' ')
  278.         cmd++;
  279.         rexxmsg->rm_Result1 = 0;
  280.         rexxmsg->rm_Result2 = 0;
  281.  
  282.         if(bringer_down)
  283.         rexxmsg->rm_Result1 = RXERRORIMGONE;
  284.         else
  285.         {
  286.         VALUE res;
  287.         o_rexx_msg = rexxmsg ;
  288.         cursor(curr_vw, CURS_OFF);
  289.         res = eval_string(cmd, FALSE);
  290.         if(res)
  291.         {
  292.             if(STRINGP(res))
  293.             reply_rexx_cmd(rexxmsg, 0, 0, VSTR(res));
  294.             else if(NUMBERP(res))
  295.             {
  296.             u_char buf[32];
  297.             sprintf(buf, "%d", VNUM(res));
  298.             reply_rexx_cmd(rexxmsg, 0, 0, buf);
  299.             }
  300.             else if(res == sym_nil)
  301.             reply_rexx_cmd(rexxmsg, 5, 0, NULL);
  302.             else
  303.             reply_rexx_cmd(rexxmsg, 0, 0, NULL);
  304.         }
  305.         else
  306.             rexxmsg->rm_Result1 = RXERRORNOCMD;
  307.         cursor(curr_vw, CURS_ON);
  308.         }
  309.         o_rexx_msg = NULL ;
  310.         ReplyMsg((struct Message *)rexxmsg);
  311.     }
  312.     }
  313. }
  314.  
  315. static bool
  316. open_rexx_lib(void)
  317. {
  318.     if(RexxSysBase || (RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L)))
  319.     return(TRUE);
  320.     return(FALSE);
  321. }
  322.  
  323. static struct RexxMsg *
  324. send_rexx_cmd(u_char *s, int(*f)(), u_char *p1, u_char *p2, u_char *p3, long m)
  325. {
  326.     struct MsgPort *rexxport;
  327.     struct RexxMsg *rexxmsg;
  328.  
  329.     if((!rexx_port) || (still_need_replies > MAXRXOUTSTANDING-1))
  330.     return(FALSE);
  331.     rexxmsg = NULL;
  332.     if(open_rexx_lib()
  333.        && (rexxmsg = CreateRexxMsg(rexx_port, RX_EXTEN, rexx_port->mp_Node.ln_Name))
  334.        && (rexxmsg->rm_Args[0] = CreateArgstring(s, (long)strlen(s))))
  335.     {
  336.     rexxmsg->rm_Action = RXCOMM | m;
  337.     rexxmsg->rm_Args[1] = (u_char *)f;
  338.     rexxmsg->rm_Args[2] = p1;
  339.     rexxmsg->rm_Args[3] = p2;
  340.     rexxmsg->rm_Args[4] = p3;
  341.     rexxmsg->rm_Node.mn_Node.ln_Name = RXSDIR;
  342.     Forbid();
  343.     if(rexxport = FindPort(RXSDIR))
  344.         PutMsg(rexxport, (struct Message *)rexxmsg);
  345.     Permit();
  346.     if(rexxport)
  347.     {
  348.         still_need_replies++;
  349.         return(rexxmsg);
  350.     }
  351.     else
  352.         DeleteArgstring(rexxmsg->rm_Args[0]);
  353.     }
  354.     if(rexxmsg)
  355.     DeleteRexxMsg(rexxmsg);
  356.     close_rexx_lib();
  357.     return(FALSE);
  358. }
  359.  
  360. struct RexxMsg *
  361. async_rexx_cmd(u_char *s)
  362. {
  363.     return(send_rexx_cmd(s, NULL, NULL, NULL, NULL, 0));
  364. }
  365.  
  366. struct RexxMsg *
  367. async_rexx_string(u_char *s)
  368. {
  369.     return(send_rexx_cmd(s, NULL, NULL, NULL, NULL, RXFF_STRING));
  370. }
  371.  
  372. static void
  373. reply_to_it(struct RexxMsg *msg)
  374. {
  375.     struct RexxMsg *omsg = (struct RexxMsg *)(msg->rm_Args[2]);
  376.     reply_rexx_cmd(omsg, msg->rm_Result1, msg->rm_Result2,
  377.            (u_char *)msg->rm_Result2);
  378.     ReplyMsg((struct Message *)omsg);
  379. }
  380.  
  381. struct RexxMsg *
  382. sync_rexx_cmd(u_char *s, bool isMac, struct RexxMsg *msg)
  383. {
  384.     return(send_rexx_cmd(s, reply_to_it, (u_char *)msg, NULL, NULL,
  385.              isMac ? 0 : RXFF_STRING));
  386. }
  387.  
  388. void
  389. reply_rexx_cmd(struct RexxMsg *msg, long primary, long secondary,
  390.            u_char *string)
  391. {
  392.     if(!primary && (msg->rm_Action & (1L << RXFB_RESULT)))
  393.     {
  394.     if(string && open_rexx_lib())
  395.         secondary = (long)CreateArgstring(string, (long)strlen(string));
  396.     else
  397.         secondary = 0L;
  398.     }
  399.     msg->rm_Result1 = primary;
  400.     msg->rm_Result2 = secondary;
  401.     close_rexx_lib();
  402. }
  403.